package cn.hamster3.mc.plugin.core.bukkit.command;

import cn.hamster3.mc.plugin.core.bukkit.constant.CoreMessage;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.stream.Collectors;

@SuppressWarnings("unused")
public abstract class ParentCommand extends ChildCommand {
    @NotNull
    private final List<ChildCommand> childCommands;

    public ParentCommand() {
        childCommands = new ArrayList<>();
    }

    @NotNull
    public abstract JavaPlugin getPlugin();

    @NotNull
    @Override
    public abstract String getName();

    @Nullable
    public ParentCommand getParent() {
        return null;
    }

    @NotNull
    public List<ChildCommand> getChildCommands() {
        return childCommands;
    }

    @NotNull
    @Override
    public String getUsage() {
        ParentCommand parent = getParent();
        if (parent == null) {
            return "/" + getName();
        }
        return parent.getUsage() + " " + getName();
    }

    @Override
    public boolean hasPermission(@NotNull CommandSender sender) {
        return true;
    }

    @Override
    public @NotNull String getDescription() {
        return "";
    }

    public void register() {
        JavaPlugin plugin = getPlugin();
        PluginCommand command = plugin.getCommand(getName());
        if (command == null) {
            throw new IllegalArgumentException("在插件 " + plugin.getName() + " 中未找到指令 " + getName());
        }
        command.setExecutor(this);
        command.setTabCompleter(this);
        plugin.getLogger().info("已注册指令 " + getUsage());
    }

    /**
     * 获取所有子命令
     * <p>
     * 如果子命令也是 ParentCommand 类型，则继续递归获取该 ParentCommand 的子命令
     *
     * @return 所有子命令
     */
    @NotNull
    public List<ChildCommand> getEndChildCommands() {
        ArrayList<ChildCommand> list = new ArrayList<>();
        for (ChildCommand command : childCommands) {
            if (command instanceof ParentCommand) {
                list.addAll(((ParentCommand) command).getEndChildCommands());
            } else {
                list.add(command);
            }
        }
        return list;
    }

    public void addChildCommand(@NotNull ChildCommand command) {
        childCommands.add(command);
    }

    @NotNull
    public Map<String, String> getCommandHelp(CommandSender sender) {
        HashMap<String, String> map = new HashMap<>();
        for (ChildCommand child : childCommands) {
            if (!child.hasPermission(sender)) {
                continue;
            }
            if (child instanceof ParentCommand) {
                Map<String, String> childMap = ((ParentCommand) child).getCommandHelp(sender);
                map.putAll(childMap);
                continue;
            }
            map.put(getUsage() + " " + child.getUsage(), child.getDescription());
        }
        return map;
    }

    public void sendHelp(@NotNull CommandSender sender) {
        sender.sendMessage("§e==================== [ " + getName() + " 使用帮助] ====================");
        Map<String, String> helpMap = getCommandHelp(sender);
        int maxLength = helpMap.keySet().stream()
                .map(String::length)
                .max(Integer::compareTo)
                .orElse(-1);
        ArrayList<Map.Entry<String, String>> list = new ArrayList<>(helpMap.entrySet());
        list.sort(Map.Entry.comparingByKey());
        for (Map.Entry<String, String> entry : list) {
            sender.sendMessage(String.format("§a%-" + maxLength + "s   - %s", entry.getKey(), entry.getValue()));
        }
    }

    @Override
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
        if (!hasPermission(sender)) {
            CoreMessage.COMMAND_NOT_HAS_PERMISSION.show(sender);
            return true;
        }
        if (args.length == 0) {
            sendHelp(sender);
            return true;
        }
        for (ChildCommand childCommand : childCommands) {
            if (!childCommand.getName().equalsIgnoreCase(args[0])) {
                continue;
            }
            if (!childCommand.hasPermission(sender)) {
                CoreMessage.COMMAND_NOT_HAS_PERMISSION.show(sender);
                return true;
            }
            return childCommand.onCommand(sender, command, label, Arrays.copyOfRange(args, 1, args.length));
        }
        CoreMessage.COMMAND_NOT_FOUND.show(sender);
        return true;
    }

    @Override
    public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
        if (args.length == 0) {
            return childCommands.stream()
                    .filter(o -> o.hasPermission(sender))
                    .map(ChildCommand::getName)
                    .collect(Collectors.toList());
        }
        for (ChildCommand child : childCommands) {
            if (args[0].equalsIgnoreCase(child.getName())) {
                return child.onTabComplete(sender, command, alias, Arrays.copyOfRange(args, 1, args.length));
            }
        }
        args[0] = args[0].toLowerCase();
        return childCommands.stream()
                .filter(o -> o.hasPermission(sender))
                .map(ChildCommand::getName)
                .filter(o -> o.toLowerCase().startsWith(args[0].toLowerCase()))
                .collect(Collectors.toList());
    }
}
